home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / 021-030 / amok21 / hotkey / hotkey.mod < prev    next >
Text File  |  1993-11-04  |  7KB  |  212 lines

  1. (*---------------------------------------------------------------------------
  2.     :Program.     HotKey.mod
  3.     :Contents.      Simple Installation eines Input-Handlers und einer
  4.     :Contents.      'heißen' Taste, also Support für Hintergrundprogramme.
  5.     :Author.      Bernd Preusing
  6.     :Address.      Gerhardstr. 16  D-2200 Elmshorn
  7.     :Phone.      04121/22486
  8.     :Copyright.      Public Domain
  9.     :Language.      Modula-2
  10.     :Translator.  M2Amiga V3.2e
  11.     :History.      V1.0 Preusing 01-Apr-89 (kein Scherz!)
  12.     :Bugs.      nicht reentrant
  13.     :Remark.      Power to the Bauer!
  14. ---------------------------------------------------------------------------*)
  15. IMPLEMENTATION MODULE HotKey;
  16.  
  17. FROM SYSTEM     IMPORT    ADR, ADDRESS, LONGSET, CAST, INLINE;
  18. FROM Arts     IMPORT    CurrentLevel, Terminate, TermProcedure, Assert;
  19. FROM Exec     IMPORT    Interrupt, IOStdReqPtr, MemReqs, MemReqSet,
  20.             Message, MessagePtr, MsgPortPtr,
  21.             AllocMem, CloseDevice, DoIO, FindPort, FreeMem,
  22.             GetMsg, OpenDevice, PutMsg, WaitPort;
  23. FROM ExecSupport IMPORT    CreatePort, DeletePort, CreateStdIO, DeleteStdIO;
  24. FROM Input     IMPORT    inputName, addHandler, remHandler, writeEvent;
  25. FROM InputEvent     IMPORT    Class, Qualifiers, QualifierSet, InputEventPtr;
  26.  
  27. CONST
  28.    MemType = MemReqSet{public, memClear}; (* spart Tipparbeit *)
  29.  
  30.    (* Diese Qualifier werden beim Vergleich nicht berücksichtigt: *)
  31.    UnusedSet = QualifierSet{multiBroadcast, capsLock, relativeMouse};
  32.  
  33.    STOPYOU = 1234H; (* magic, irgendwas Spezielles *)
  34.    ISHOT  = 478AH; (* dito *)
  35.  
  36.    A0 = 8+0; A1 = 8+1; (* Register *)
  37.  
  38. TYPE
  39.    CodeRecPtr = POINTER TO CodeRec;
  40.    CodeRec = RECORD
  41.            code: CARDINAL;
  42.            qualifier: QualifierSet
  43.          END;
  44.  
  45. VAR
  46.    StartLevel: INTEGER;
  47.    ActionPort, (* 2 Ports, sonst gibt es Message-Salat (probiert!) *)
  48.    DevicePort: MsgPortPtr;
  49.    DeviceIO: IOStdReqPtr;
  50.    HotKeyIntr: Interrupt;
  51.    HotKey: CodeRec;
  52.    AddedHandler: BOOLEAN;
  53.  
  54. (* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv *)
  55. (* Input-Handler: (liegt in der Kette vor Intuition) *)
  56. (* $S- *)
  57. (* Verbiete Stackprüfung, wir sind hier in einem fremden Task. *)
  58. (* Andere Laufzeitfehler führen zum Guru. *)
  59. (* Register A0 zeigt auf die InputEvents, A1 auf meine Daten, *)
  60. (* in D0 gebe ich zurück, was ich nicht verarbeiten kann oder will *)
  61. (* Forbid(), Disable() usw. sind völlig überflüssig! *)
  62. PROCEDURE InputHandler(events{A0}: InputEventPtr;
  63.                keys{A1}  : CodeRecPtr
  64.                ): InputEventPtr;
  65. VAR OldEvents: InputEventPtr;
  66.     Msg      : MessagePtr;
  67. BEGIN
  68.   (* $Z- Option: Systemparameter gleich in die Register *)
  69.   (* Alle Register auf den Stack, A4 und A5 übernimmt der Compiler *)
  70.   INLINE(48E7H,0011111100110010L); (* MOVEM.L D2-D7,A2-A3/A6,-(A7) *)
  71.   OldEvents:=events;
  72.   WHILE events # NIL DO (* WITH wäre hier Unsinn! *)
  73.     IF (events^.class = rawkey) AND (events^.code = keys^.code)
  74.      AND ((events^.qualifier-UnusedSet) = keys^.qualifier) THEN
  75.        events^.class:=null; (* einfach ungültig machen *)
  76.        Msg:=AllocMem(SIZE(Message),MemType);
  77.        IF Msg # NIL THEN
  78.          Msg^.length:=ISHOT;
  79.          PutMsg(ActionPort,Msg);
  80.        END;
  81.     END;
  82.     events:=events^.nextEvent;
  83.   END;
  84.   (* Gerettete Register wiederherstellen *)
  85.   INLINE(4CDFH,0100110011111100L); (* MOVEM.L (A7)+,D2-D7,A2-A3/A6 *)
  86.   RETURN OldEvents
  87. END InputHandler;
  88. (* $S= $Z= *)
  89. (* alte Stackprüfung wiederherstellen *)
  90. (* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *)
  91.  
  92. PROCEDURE AddEvents(events: InputEventPtr);
  93. VAR Next: InputEventPtr;
  94. BEGIN
  95.   WHILE events # NIL DO
  96.     Next:=events^.nextEvent;
  97.     WITH DeviceIO^ DO
  98.       command:=writeEvent;
  99.       data:=events; (* events^.next wird vom device gelöscht! *)
  100.     END;
  101.     DoIO(DeviceIO); (* immer ok *)
  102.     events:=Next;
  103.   END;
  104. END AddEvents;
  105.  
  106. PROCEDURE InstallHandler(VAR Intr: Interrupt; install:BOOLEAN);
  107. BEGIN
  108.   WITH DeviceIO^ DO
  109.     IF install THEN
  110.       command:=addHandler
  111.     ELSE
  112.       command:=remHandler
  113.     END;
  114.     data:=ADR(Intr);
  115.     length:=SIZE(Intr);
  116.   END;
  117.   DoIO(DeviceIO); (* immer ok *)
  118. END InstallHandler;
  119.  
  120. PROCEDURE InstallKey(Key:CARDINAL; QSet:QualifierSet; KeyProc:PROC;
  121.              PortName:ADDRESS);
  122. VAR
  123.     OldPort: MsgPortPtr;
  124.     MyMsg: MessagePtr;
  125.     Value: CARDINAL;
  126. BEGIN
  127.   OldPort:=FindPort(PortName);
  128.   IF OldPort # NIL THEN (* ist schon da, also alles beenden *)
  129.     MyMsg:=AllocMem(SIZE(Message),MemType);
  130.     Assert(MyMsg#NIL,ADR("can't create Message"));
  131.     MyMsg^.length:=STOPYOU;
  132.     PutMsg(OldPort,MyMsg); (* FreeMem macht der andere! *)
  133.     Terminate(CurrentLevel()); (* das war's dann. *)
  134.   ELSE
  135.     ActionPort:=CreatePort(PortName,0);
  136.     Assert(ActionPort#NIL,ADR("can't create ActionPort!"));
  137.     WITH HotKeyIntr DO
  138.       node.pri:=51; (* intuition = 50 *)
  139.       data:=ADR(HotKey);
  140.       code:=ADR(InputHandler);
  141.     END;
  142.     HotKey.code:=Key;
  143.     HotKey.qualifier:=QSet-UnusedSet;
  144.     LOOP (* Endlose Warteschleife *)
  145.       InstallHandler(HotKeyIntr, TRUE); (* Handler einschalten *)
  146.       AddedHandler:=TRUE;
  147.       WaitPort(ActionPort);
  148.       MyMsg:=GetMsg(ActionPort);
  149.       InstallHandler(HotKeyIntr, FALSE); (* Handler besser ausschalten *)
  150.       AddedHandler:=FALSE;
  151.       Value:=MyMsg^.length;
  152.       FreeMem(MyMsg,SIZE(Message));
  153.       IF Value = ISHOT THEN
  154.         KeyProc() (* un nu komms Du *)
  155.       ELSIF Value = STOPYOU THEN
  156.         Terminate(CurrentLevel()) (* aus und vorbei! *)
  157.       ELSE
  158.         Assert(FALSE,ADR('HotKey: got illegal message'))
  159.       END;
  160.     END; (* LOOP *)
  161.   END;
  162. END InstallKey;
  163.  
  164. PROCEDURE OpenInput():BOOLEAN;
  165. BEGIN
  166.   DevicePort:=CreatePort(NIL,0);
  167.   IF DevicePort = NIL THEN RETURN FALSE END;
  168.   DeviceIO:=CreateStdIO(DevicePort);
  169.   IF DeviceIO = NIL THEN RETURN FALSE END;
  170.   OpenDevice(ADR(inputName),0,DeviceIO,LONGSET{});
  171.   RETURN DeviceIO^.error = 0
  172. END OpenInput;
  173.  
  174. PROCEDURE Cleanup; (* TermProcedure *)
  175. VAR Msg: MessagePtr;
  176. BEGIN
  177.   IF CurrentLevel() <= StartLevel THEN
  178.     IF AddedHandler THEN
  179.       InstallHandler(HotKeyIntr, FALSE);
  180.       AddedHandler:=FALSE;
  181.     END;
  182.     IF DeviceIO # NIL THEN
  183.       IF CAST(LONGINT,DeviceIO^.unit) > 0 THEN
  184.         (* nicht NIL, nicht -1 *)
  185.         CloseDevice(DeviceIO)
  186.       END;
  187.       DeleteStdIO(DeviceIO); DeviceIO:=NIL
  188.     END;
  189.     IF DevicePort # NIL THEN
  190.       DeletePort(DevicePort); DevicePort:=NIL
  191.     END;
  192.     IF ActionPort # NIL THEN
  193.       LOOP (* Port leeren *)
  194.         Msg:=GetMsg(ActionPort);
  195.         IF Msg=NIL THEN EXIT END;
  196.         FreeMem(Msg,SIZE(Message));
  197.       END;
  198.       DeletePort(ActionPort); ActionPort:=NIL
  199.     END;
  200.   END
  201. END Cleanup;
  202.  
  203. BEGIN (* HotKey.mod *)
  204.   DevicePort:=NIL;
  205.   ActionPort:=NIL;
  206.   DeviceIO:=NIL;
  207.   AddedHandler:=FALSE;
  208.   StartLevel:=CurrentLevel();
  209.   TermProcedure(Cleanup);
  210.   Assert(OpenInput(),ADR("can't open input.device"));
  211. END HotKey.mod
  212.